package com.vvv.designpattern.ordermanagement.listener;

import com.vvv.designpattern.constants.RedisConstants;
import com.vvv.designpattern.ordermanagement.command.command.OrderCommand;
import com.vvv.designpattern.ordermanagement.command.invoker.OrderCommandInvoker;
import com.vvv.designpattern.ordermanagement.state.OrderState;
import com.vvv.designpattern.ordermanagement.state.OrderStateChangeAction;
import com.vvv.designpattern.pojo.Order;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.messaging.Message;
import org.springframework.statemachine.annotation.OnTransition;
import org.springframework.statemachine.annotation.WithStateMachine;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

/**
 * @author vvv
 * @date 2023-11-21 12 58
 * discription 对应观察者模式，监听spring状态机，同步redis中状态机的状态和redis中订单的状态的
 */
@Component
@WithStateMachine(name="orderStateMachine")
public class OrderStateListener {

    @Resource
    private RedisTemplate redisTemplate;

    @Resource
    private OrderCommand orderCommand;

    /**
     * Message是我们在Service层发送给spring状态机的，然后spring状态机再发送给OrderStateListener的
     * @param message
     * @return
     */
    @OnTransition(source = "ORDER_WAIT_PAY", target = "ORDER_WAIT_SEND")
    public boolean payToSend(Message<OrderStateChangeAction> message) {

        System.out.println("到达payToSend");
        // 1. message中获取订单，message里面的order是从redis中获取的
        Order order = (Order) message.getHeaders().get("order");
        // 2. 判断当前订单状态是不是待支付
        if (order == null || order.getOrderState() != OrderState.ORDER_WAIT_PAY) {
            throw new UnsupportedOperationException("Order state error! ");
        }
        // 3. 支付成功后修改订单状态为待发货，并更新redis
        order.setOrderState(OrderState.ORDER_WAIT_SEND);
        String key = RedisConstants.ORDER_STATE_KEY_PREFIX + order.getOrderId();
        redisTemplate.opsForValue().set(key, order);
        // 命令模式
        OrderCommandInvoker orderCommandInvoker = new OrderCommandInvoker();
        orderCommandInvoker.invoke(orderCommand, order);
        return true;
    }

    @OnTransition(source = "ORDER_WAIT_SEND", target = "ORDER_WAIT_RECEIVE")
    public boolean sendToReceive(Message<OrderStateChangeAction> message) {

        System.out.println("到达sendToReceive");
        // 1. message中获取订单，message里面的order是从redis中获取的
        Order order = (Order) message.getHeaders().get("order");
        // 2. 判断当前订单状态是不是待发货
        if (order == null || order.getOrderState() != OrderState.ORDER_WAIT_SEND) {
            throw new UnsupportedOperationException("Order state error! ");
        }
        // 3. 支付成功后修改订单状态为待收货状态，并更新redis
        order.setOrderState(OrderState.ORDER_WAIT_RECEIVE);
        String key = RedisConstants.ORDER_STATE_KEY_PREFIX + order.getOrderId();
        redisTemplate.opsForValue().set(key, order);
        // 命令模式
        OrderCommandInvoker orderCommandInvoker = new OrderCommandInvoker();
        orderCommandInvoker.invoke(orderCommand, order);
        return true;
    }

    @OnTransition(source = "ORDER_WAIT_RECEIVE", target = "ORDER_FINISH")
    public boolean receiveToFinish(Message<OrderStateChangeAction> message) {
        System.out.println("到达receiveToFinish");
        // 1. message中获取订单，message里面的order是从redis中获取的
        Order order = (Order) message.getHeaders().get("order");
        // 2. 判断当前订单状态是不是待收货状态
        if (order == null || order.getOrderState() != OrderState.ORDER_WAIT_RECEIVE) {
            throw new UnsupportedOperationException("Order state error! ");
        }
        // 3. 支付成功后修改订单状态为完成，并删除redis
        order.setOrderState(OrderState.ORDER_FINISH);
        String key = RedisConstants.ORDER_STATE_KEY_PREFIX + order.getOrderId();
        redisTemplate.delete(key);
        // 4. 删除redis中这个订单对应的状态机
        String stateMachineKey = RedisConstants.STATE_MACHINE_KEY_PREFIX + order.getOrderId();
        redisTemplate.delete(stateMachineKey);
        // 命令模式
        OrderCommandInvoker orderCommandInvoker = new OrderCommandInvoker();
        orderCommandInvoker.invoke(orderCommand, order);
        return true;
    }
}
